#include "tlr.h"
#include <QHostAddress>
#include <QNetworkDatagram>
#include <QFile>
#include <QTimer>
#include <QToolTip>

/*
 * 构造函数
 * parent : 父类初始化参数
 */
TLR::TLR(QObject *parent) : QObject (parent)
{

}

Q_GLOBAL_STATIC(TLR,nlr)
/*
 * 获取单例
 * 返回值 : 单例
 */
TLR *TLR::get()
{
    return nlr();
}

/*
 * 获取指定IP的网络接口信息
 * npcip : 指定的IP
 * 返回值 : 网络接口信息
 */
QNetworkInterface TLR::getNetInfoAsnIP(QHostAddress npcip)
{
    QNetworkInterface nnetworkinterface;
    auto nlistnetinfo = QNetworkInterface::allInterfaces();
    for(auto &nnetinfo:nlistnetinfo){
        auto nlistaddress = nnetinfo.addressEntries();
        for(auto &naddress:nlistaddress){
            if(naddress.ip() == npcip){
                nnetworkinterface = nnetinfo;
            }
        }
    }
    return nnetworkinterface;
}

/*
 * 查询指定IP对应的MYIP信息
 * npcip : 指定的IP
 * 返回值 : 网络接口信息
 */
TMyIP TLR::getTMyIPAsnIP(QHostAddress npcip)
{
    TMyIP nmyip;
    auto nlistnetinfo = QNetworkInterface::allInterfaces();
    for(auto &nnetinfo:nlistnetinfo){
        auto nlistaddress = nnetinfo.addressEntries();
        for(auto &naddress:nlistaddress){
            if(naddress.ip() == npcip){
                //本机IP
                addressToIP4(npcip,nmyip.ip);
                //子网掩码
                addressToIP4(naddress.netmask(),nmyip.netmask);
                //MAC地址
                stringToMac6(nnetinfo.hardwareAddress(),nmyip.mac);
                //网关
#ifdef Q_OS_ANDROID
                //nmyip.GateWay = QHostAddress(TAndroidSupport::getGateWay());
#endif
            }
        }
    }
    return nmyip;
}

/*
 * 获取本机所有IPV4 IP信息(不会返回环回地址)
 * 返回值 : IP地址
 */
QList<QHostAddress> TLR::getAllAddressIPv4()
{
    QList<QHostAddress> nlistaddress;
    auto nalladdress = QNetworkInterface::allAddresses();
    for(auto &naddress:nalladdress){
        if(!naddress.isLoopback()){
            if(naddress.protocol() == QAbstractSocket::IPv4Protocol){
                nlistaddress.append(naddress);
            }
        }
    }
    return nlistaddress;
}

/**********
 * 辅助_4字节IP转地址
 * nip    :  待转换IP
 * 返回值  :  IP地址
**********/
QHostAddress TLR::ip4toAddress(const u8 nip[])
{
    u8 niptmp[4];
    niptmp[0] = nip[3];
    niptmp[1] = nip[2];
    niptmp[2] = nip[1];
    niptmp[3] = nip[0];
    QHostAddress nipaddr;
    quint32 nipint;
    memcpy(&nipint,niptmp,4);
    nipaddr.setAddress(nipint);
    return nipaddr;
}

/*
 * 辅助_IP地址转4字节
 * nipstr  :  IP地址
 * nip     :  4字节IP
 */
void TLR::addressToIP4(QHostAddress nipaddr,u8 nip[4])
{
    //由于计算机是按照小端存储基本数据类型的所以这里转换的IP地址
    //需要反一下才行
    quint32 nipint32 = nipaddr.toIPv4Address();
    u8 niptmp[4];
    memcpy(niptmp,&nipint32,4);
    nip[0] = niptmp[3];
    nip[1] = niptmp[2];
    nip[2] = niptmp[1];
    nip[3] = niptmp[0];
}

/*
 * 辅助_MAC字符串转6字节
 * nmacstr  :  IP地址
 * nmac     :  4字节IP
 * nsplit   :  分割符(可缺省)
 */
void TLR::stringToMac6(const QString &nmacstr, u8 nmac[],const QString &nsplit)
{
    memset(nmac,0x00,6);
    QStringList nmaclist = nmacstr.split(nsplit);
    if(nmaclist.size() == 6){
        for(int ii=0;ii<6;ii++){
            nmac[ii] = static_cast<u8>(nmaclist.at(ii).toInt(nullptr,16));
        }
    }
}

/*
 * 辅助_MAC地址6字节转字符串
 * nmac   : mac地址6字节
 * nsplit : 分割符(可缺省)
 */
QString TLR::mac6ToString(const u8 nmac[], const QString &nsplit)
{
    QString nmacstr;
    nmacstr = QString("%1"+nsplit+"%2"+nsplit+"%3"+nsplit+"%4"+nsplit+"%5"+nsplit+"%6")
            .arg(nmac[0],2,16,QChar('0'))
            .arg(nmac[1],2,16,QChar('0'))
            .arg(nmac[2],2,16,QChar('0'))
            .arg(nmac[3],2,16,QChar('0'))
            .arg(nmac[4],2,16,QChar('0'))
            .arg(nmac[5],2,16,QChar('0'));
    nmacstr = nmacstr.toUpper();
    return nmacstr;
}

/*
 * 辅助_获取指定IP的MAC地址(仅WIN平台)
 * nip   : 指定IP
 * 返回值 : MAC地址
 */
void TLR::getMacAsnIP(const QHostAddress &nip, u8 nmac[])
{
#ifdef Q_OS_WIN
    //IP要转换位IPV4地址
//    QHostAddress nipv4 = QHostAddress(nip.toIPv4Address());
//    IPAddr ndestip = 0;
//    ULONG nphysAddrLen = 6;  /* default to length of six bytes */
//    ndestip = inet_addr(nipv4.toString().toUtf8().data());
//    if(!nipv4.isBroadcast()) {
//        SendARP(ndestip,INADDR_ANY,nmac,&nphysAddrLen);
//    }
//    //过滤非法数据(全0xff)
//    if(nmac[0] == 0xff && nmac[0] == 0xff && nmac[0] == 0xff &&
//            nmac[0] == 0xff && nmac[0] == 0xff && nmac[0] == 0xff) {
//        memset(nmac,0x00,6);
//    }
#endif
}

/*
 * 计算offsetof(因为传统的offsetof不能加入变量表达式)
 * nsta  : 起始位置
 * ndest : 比较位置
 * 返回值 : 偏移量
 */
int TLR::dynOffsetof(const void *nsta, const void *ndest)
{
    int noffset = 0;
    noffset = static_cast<const char*>(ndest) -
            static_cast<const char*>(nsta);
    return noffset;
}

/*
 * LR标准协议_读取数据
 * nequidstr : 设备识别字
 * startpos  : 起始位置
 * paranum   : 数据数量
 * 返回值     : 数据包
 */
QList<QByteArray> TLR::rdPara(QString nequidstr,int startpos, int paranum,quint16 naddr)
{
    QList<QByteArray> nlistbytes;
    int npkgnum = paranum / 1024;
    npkgnum += paranum % 1024?1:0;
    for(int ipkg=0;ipkg<npkgnum;ipkg++){
        TUDPSysPara nudpsyspara;
        //指令
        strcpy(nudpsyspara.Cmd,"SetPara");
        //地址
        nudpsyspara.Cmd[8] = char(naddr % 256);
        nudpsyspara.Cmd[9] = char(naddr / 256);
        //识别字
        strncpy(nudpsyspara.IdentifyingCode,nequidstr.toStdString().data(),20);
        nudpsyspara.StartByte = 0xca;
        nudpsyspara.CmdType = 0x03;
        //起始地址
        nudpsyspara.ParaStaAdd = static_cast<u16>(startpos + ipkg*1024);
        //数据数量
        u16 nremainsize = static_cast<u16>(startpos + paranum) - nudpsyspara.ParaStaAdd;
        nudpsyspara.ParaNum = nremainsize >= 1024?1024:nremainsize;

        QByteArray nsndbyte;
        nsndbyte.resize(sizeof (TUDPSetParaConfirm));
        memcpy(nsndbyte.data(),&nudpsyspara,static_cast<size_t>(nsndbyte.size()));
        nlistbytes.append(nsndbyte);
    }
    return nlistbytes;
}

/*
 * LR标准协议_下载数据
 * nequidstr : 设备识别字
 * startpos  : 起始位置
 * paranum   : 数据量
 * dp        : 源数据指针
 * 返回值     : 数据包
 */
QList<QByteArray> TLR::wrPara(QString nequidstr,int startpos, int paranum, const void *dp,quint16 naddr)
{
    QList<QByteArray> nlistbytes;
    int npkgnum = paranum / 1024;
    npkgnum += paranum % 1024?1:0;
    for(int ipkg=0;ipkg<npkgnum;ipkg++){
        TUDPSysPara nudpsyspara;
        //指令
        strcpy(nudpsyspara.Cmd,"SetPara");
        //地址
        nudpsyspara.Cmd[8] = char(naddr % 256);
        nudpsyspara.Cmd[9] = char(naddr / 256);
        //识别字
        strncpy(nudpsyspara.IdentifyingCode,nequidstr.toStdString().data(),20);
        nudpsyspara.StartByte = 0xca;
        nudpsyspara.CmdType = 0x10;
        //起始地址
        nudpsyspara.ParaStaAdd = static_cast<u16>(startpos + ipkg*1024);
        //数据数量
        u16 nremainsize = static_cast<u16>(startpos + paranum) - nudpsyspara.ParaStaAdd;
        nudpsyspara.ParaNum = nremainsize >= 1024?1024:nremainsize;
        //实际数据
        memcpy(nudpsyspara.Para,reinterpret_cast<const char*>(dp)+ipkg*1024,nudpsyspara.ParaNum);

        QByteArray nsndbyte;
        nsndbyte.resize(sizeof (TUDPSetParaConfirm) + nudpsyspara.ParaNum);
        memcpy(nsndbyte.data(),&nudpsyspara,static_cast<size_t>(nsndbyte.size()));
        nlistbytes.append(nsndbyte);
    }
    return nlistbytes;
}

/*
 * LR标准协议_下载数据
 * nequidstr : 设备识别字
 * startpos  : 起始位置
 * paranum   : 数据量
 * dp        : 源数据指针
 * 返回值     : 数据包
 */
QList<QByteArray> TLR::ctlPara(QString nequidstr, int startpos, int paranum, const void *dp,quint16 naddr)
{
    QList<QByteArray> nlistbytes;
    int npkgnum = paranum / 1024;
    npkgnum += paranum % 1024?1:0;
    for(int ipkg=0;ipkg<npkgnum;ipkg++){
        TUDPSysPara nudpsyspara;
        //指令
        strcpy(nudpsyspara.Cmd,"SetPara");
        //地址
        nudpsyspara.Cmd[8] = char(naddr % 256);
        nudpsyspara.Cmd[9] = char(naddr / 256);
        //识别字
        strncpy(nudpsyspara.IdentifyingCode,nequidstr.toStdString().data(),20);
        nudpsyspara.StartByte = 0xca;
        nudpsyspara.CmdType = 0x06;
        //起始地址
        nudpsyspara.ParaStaAdd = static_cast<u16>(startpos + ipkg*1024);
        //数据数量
        u16 nremainsize = static_cast<u16>(startpos + paranum) - nudpsyspara.ParaStaAdd;
        nudpsyspara.ParaNum = nremainsize >= 1024?1024:nremainsize;
        //实际数据
        memcpy(nudpsyspara.Para,reinterpret_cast<const char*>(dp)+ipkg*1024,nudpsyspara.ParaNum);

        QByteArray nsndbyte;
        nsndbyte.resize(sizeof (TUDPSetParaConfirm) + nudpsyspara.ParaNum);
        memcpy(nsndbyte.data(),&nudpsyspara,static_cast<size_t>(nsndbyte.size()));
        nlistbytes.append(nsndbyte);
    }
    return nlistbytes;
}

/*
 * LR标准协议_读取FLASH数据
 * address : 串口通讯时用的，是设备地址，网络时不关心
 * staadd  : 要擦除或编程的 FLASH 的绝对地址  操作45DB161时，以528为单位，操作CPU内部FLASH时，以1024为单位
 * datlen  : 就是要操作的数据  操作45db16的时候不可以超过 528
 * 返回值   : 数据包
 */
QList<QByteArray> TLR::rdParaFlash(int address, int staadd, int datlen)
{
    QList<QByteArray> nlistbytes;
    int npkgnum = datlen / 1024;
    npkgnum += datlen % 1024?1:0;
    for(int ipkg=0;ipkg<npkgnum;ipkg++){
        TFlashProg nflashprog;
        //串口地址
        nflashprog.Address = static_cast<u16>(address);
        //指令
        strcpy(nflashprog.Cmd,"FlashReadPage");
        //起始地址
        nflashprog.StaAdd = static_cast<u32>(staadd + 1024*ipkg);
        //数据长度
        u32 nremainsize = static_cast<u32>(datlen + staadd) - nflashprog.StaAdd;
        nflashprog.DatLen = nremainsize >= 1024?1024:nremainsize;
        QByteArray nsndbyte;
        nsndbyte.resize(sizeof (TFlashProg));
        memcpy(nsndbyte.data(),&nflashprog,static_cast<size_t>(nsndbyte.size()));
        nlistbytes.append(nsndbyte);
    }
    return nlistbytes;
}

/*
 * LR标准协议_下载FLASH数据
 * address : 串口通讯时用的，是设备地址，网络时不关心
 * staadd  : 要擦除或编程的 FLASH 的绝对地址  操作45DB161时，以528为单位，操作CPU内部FLASH时，以1024为单位
 * datlen  : 就是要操作的数据  操作45db16的时候不可以超过 528
 * pdata   : 原始数据
 * 返回值   : 数据包
 */
QList<QByteArray> TLR::wrParaFlash(int address, int staadd, int datlen, const void *pdata)
{
    QList<QByteArray> nlistbytes;
    int npkgnum = datlen / 1024;
    npkgnum += datlen % 1024?1:0;
    for(int ipkg=0;ipkg<npkgnum;ipkg++){
        TFlashProg nflashprog;
        //串口地址
        nflashprog.Address = static_cast<u16>(address);
        //指令
        strcpy(nflashprog.Cmd,"FlashWritePage");
        //起始地址
        nflashprog.StaAdd = static_cast<u32>(staadd + 1024*ipkg);
        //数据长度
        u32 nremainsize = static_cast<u32>(datlen + staadd) - nflashprog.StaAdd;
        nflashprog.DatLen = nremainsize >= 1024?1024:nremainsize;
        //数据
        memcpy(nflashprog.databuf,reinterpret_cast<const char*>(pdata)+1024*ipkg,nflashprog.DatLen);
        QByteArray nsndbyte;
        nsndbyte.resize(sizeof (TFlashProg));
        memcpy(nsndbyte.data(),&nflashprog,static_cast<size_t>(nsndbyte.size()));
        nlistbytes.append(nsndbyte);
    }
    return nlistbytes;
}

/*
 * LR标准协议_合成数据
 * nequidstr : 设备识别字
 * startpos  : 起始位置
 * paranum   : 数据数量
 * ncmdtype  : 指令类型
 * ncmd      : 指令
 * 返回值     : 数据包
 */
QList<QByteArray> TLR::makePara(QString nequidstr, int startpos, int paranum, int ncmdtype, const QByteArray &ncmd)
{
    QList<QByteArray> nlistbytes;
    int npkgnum = paranum / 1024;
    npkgnum += paranum % 1024?1:0;
    if(paranum == 0) {
        npkgnum = 1;
    }
    for(int ipkg=0;ipkg<npkgnum;ipkg++){
        TUDPSysPara nudpsyspara;
        //指令
        strncpy(nudpsyspara.Cmd,ncmd.constData(),9);
        //识别字
        strncpy(nudpsyspara.IdentifyingCode,nequidstr.toStdString().data(),19);
        nudpsyspara.StartByte = 0xca;
        nudpsyspara.CmdType = u8(ncmdtype);
        //起始地址
        nudpsyspara.ParaStaAdd = static_cast<u16>(startpos + ipkg*1024);
        //数据数量
        u16 nremainsize = static_cast<u16>(paranum - ipkg*1024);
        nudpsyspara.ParaNum = nremainsize >= 1024?1024:nremainsize;

        QByteArray nsndbyte;
        nsndbyte.resize(sizeof (TUDPSetParaConfirm));
        memcpy(nsndbyte.data(),&nudpsyspara,static_cast<size_t>(nsndbyte.size()));
        nlistbytes.append(nsndbyte);
    }
    return nlistbytes;
}

/*
 * LR标准协议_FLASH指令报文
 * address  : 串口通讯时用的，是设备地址，网络时不关心
 * staadd   : 要擦除或编程的 FLASH 的绝对地址  操作45DB161时，以528为单位，操作CPU内部FLASH时，以1024为单位
 * datlen   : 就是要操作的数据  操作45db16的时候不可以超过 528
 * ncmdbyte : 指令
 * 返回值    : 数据包
 */
QByteArray TLR::packFlashAddCmd(int address, int staadd, int datlen, QByteArray ncmdbyte)
{
    QByteArray nsigbyte;
    TFlashAddCmd nflashaddcmp{};
    //地址
    nflashaddcmp.Address = static_cast<u16>(address);
    //指令
    strncpy(nflashaddcmp.Cmd,ncmdbyte.data(),sizeof (nflashaddcmp.Cmd));
    //起始地址
    nflashaddcmp.StaAdd = static_cast<u32>(staadd);
    //数据长度
    nflashaddcmp.DatLen = static_cast<u32>(datlen);
    nsigbyte.resize(sizeof (nflashaddcmp));
    memcpy(nsigbyte.data(),&nflashaddcmp,static_cast<size_t>(nsigbyte.size()));
    return nsigbyte;
}

/*
 * LR标准协议_搜索在线设备
 * 返回值  :  数据包
*/
QByteArray TLR::searchEqu()
{
    QByteArray nqbyte;
    TUDPAddressPara nudpaddresspara;
    strcpy(nudpaddresspara.Cmd,"GetNetPara");
    nqbyte.resize(sizeof (nudpaddresspara));
    memcpy(nqbyte.data(),&nudpaddresspara,static_cast<size_t>(nqbyte.size()));
    return nqbyte;
}

/*
 * 广播设置IP
 * uid  : 设备UID
 * nmac : MAC地址
 * nip  : IP地址
 */
QByteArray TLR::bcastSetIP(char uid[],u8 nmac[], u8 nip[])
{
    TUDPSysPara nudpsyspara;
    //指令
    strcpy(nudpsyspara.Cmd,"BrdSetP");
    //识别字(UID + MAC)
    memcpy(nudpsyspara.IdentifyingCode,uid,14);
    memcpy(nudpsyspara.IdentifyingCode+14,nmac,6);
    nudpsyspara.StartByte = 0xca;
    nudpsyspara.CmdType = 0x06;
    //起始地址
    nudpsyspara.ParaStaAdd = offsetof(TAddressPara,ip);
    //数据数量
    nudpsyspara.ParaNum = 4;
    //实际数据
    memcpy(nudpsyspara.Para,nip,nudpsyspara.ParaNum);

    QByteArray nsndbyte;
    nsndbyte.resize(sizeof (TUDPSetParaConfirm) + nudpsyspara.ParaNum);
    memcpy(nsndbyte.data(),&nudpsyspara,static_cast<size_t>(nsndbyte.size()));
    return nsndbyte;
}

/*
 * LR标准协议_校时
 * 返回值 : 数据包
 */
QByteArray TLR::calibTime()
{
    TUDPCalibTime nudpcalibtime;
    QDateTime ndatetime = QDateTime::currentDateTime();

    strcpy(nudpcalibtime.Cmd,"CalibDateTime");
    nudpcalibtime.DT.year = static_cast<u8>(ndatetime.date().year()-2000);
    nudpcalibtime.DT.month = static_cast<u8>(ndatetime.date().month());
    nudpcalibtime.DT.date = static_cast<u8>(ndatetime.date().day());
    nudpcalibtime.DT.hour = static_cast<u8>(ndatetime.time().hour());
    nudpcalibtime.DT.min = static_cast<u8>(ndatetime.time().minute());
    nudpcalibtime.DT.sec = static_cast<u8>(ndatetime.time().second());
    nudpcalibtime.DT.msCnt = static_cast<u8>(ndatetime.time().msec());
    nudpcalibtime.DT.weekday = static_cast<u8>(ndatetime.date().dayOfWeek());
    QByteArray nsndbyte;
    nsndbyte.resize(sizeof(TUDPCalibTime));
    memcpy(nsndbyte.data(),&nudpcalibtime,sizeof (TUDPCalibTime));
    return nsndbyte;
}

/*
 * LR标准协议_IAP指令
 * ncmd    : 指令
 * 返回值   : IAP指令字节
 */
QByteArray TLR::packIapSigCmd(const QByteArray &ncmd)
{
    QByteArray niapbyte;
    TIAPSigCmd niapsigcmd;
    strncpy(niapsigcmd.Cmd,ncmd.constData(),15);
    niapbyte.resize(sizeof (niapsigcmd));
    memcpy(niapbyte.data(),&niapsigcmd,sizeof(niapsigcmd));
    return niapbyte;
}

/**
 * @brief LR标准协议_透传
 * @param port 端口
 * @param baud 波特率
 * @param data_list 数据
 * @param dire 方向 'T' 发送 'R' 接收
 * @return
 */
QList<QByteArray> TLR::packParaUartTRDat(u16 port, u16 baud, const QList<QByteArray> &data_list,char dire)
{
    QList<QByteArray> snd_data_list;
    QByteArray snd_data;
    TUartTRDat uart_tr_dat;
    for(int i=0;i<data_list.size();i++) {
        memset(&uart_tr_dat,0x00,sizeof(uart_tr_dat));
        const QByteArray &data = data_list.at(i);
        uart_tr_dat.CommPort = port;
        uart_tr_dat.len = data.size();
        uart_tr_dat.Baud = baud;
        if(dire == 'T') {
            strncpy(uart_tr_dat.Cmd,"UartTDat",16);
        }
        else if(dire == 'R') {
            strncpy(uart_tr_dat.Cmd,"UartRDat",16);
        }
        memcpy(uart_tr_dat.UartDat,data.constData(),data.size());
        snd_data.resize(offsetof(TUartTRDat,UartDat) + data.size());
        memcpy(snd_data.data(),&uart_tr_dat,snd_data.size());
        snd_data_list.append(snd_data);
    }
    return snd_data_list;
}

/*
 * 延时
 * nmsec : 毫秒
 */
void TLR::delayMs(int nmsec)
{
    if(nmsec > 0) {
        QEventLoop nloop;
        QTimer::singleShot(nmsec,&nloop,&QEventLoop::quit);
        nloop.exec();
    }
}

/*
 * UDP发送数据
 * nsndbyte : 发送的数据
 * nip      : 目标IP
 * nport    : 目标端口
 */
void TLR::udpSockAnyWrite(const QByteArray &nsndbyte, const QHostAddress &nip, int nport)
{
    m_udpSockAny->writeDatagram(nsndbyte,nip,static_cast<u16>(nport));
}

/*
 * UDP发送数据
 * nsndbytes : 发送的数据
 * nip       : 目标IP
 * nport     : 目标端口
 */
void TLR::udpSockAnyWrite(const QList<QByteArray> &nsndbytes, const QHostAddress &nip, int nport)
{
    for(const QByteArray &nsndbyte:nsndbytes) {
        m_udpSockAny->writeDatagram(nsndbyte,nip,static_cast<u16>(nport));
    }
}

/*
 * 设置IP
 * nip : IP
 */
void TLR::setMyIP(const QHostAddress &nip)
{
    m_myIP = getTMyIPAsnIP(nip);
    //重新bind
    m_udpSockAny->disconnectFromHost();
    m_udpSockAny->bind(nip);
}

/*
 * 获取本机IP
 */
TMyIP TLR::getMyIP()
{
    return m_myIP;
}

/*
 * 打开串口
 * nportname : 串口名称
 * nbaud     : 波特率
 * 返回值     : true 打开成功 false 打开失败
 */
bool TLR::openSerialPort(const QString &nportname, qint32 nbaud)
{
    bool nret = false;
    m_commUart.setPort(QSerialPortInfo(nportname));
    m_commUart.open(QSerialPort::ReadWrite);
    m_commUart.setBaudRate(nbaud);
    m_commUart.setDataBits(QSerialPort::Data8);
    m_commUart.setParity(QSerialPort::NoParity);
    m_commUart.setReadBufferSize(1024);
    nret = m_commUart.isOpen();
    return nret;
}

/*
 * 关闭串口
 */
void TLR::closeSerialPort()
{
    if(m_commUart.isOpen()) {
        m_commUart.close();
    }
}

/*
 * 获取当前使用的串口名称
 * 返回值 : 当前使用的串口名称
 */
QString TLR::getCurrentPortName()
{
    QString nportname;
    if(m_commUart.isOpen()) {
        nportname = m_commUart.portName();
    }
    return nportname;
}

/*
 * 串口发送数据
 * nsndbyte  : 待发送数据
 * nreadsize : 待接收数据长度
 */
void TLR::serialPortWrite(const QByteArray &nsndbyte,int nreadsize)
{
    if(m_commUart.isOpen() && !m_serialPortLock) {
        m_serialPortLock = true;
        m_commUart.clear();
        m_commUart.write(nsndbyte);
        //等待发送完成以及接收完成
        delayMs(int((nsndbyte.size()*10.5/m_commUart.baudRate()*1000 + nreadsize*10.5/m_commUart.baudRate()*1000 + 20)*2));
        QByteArray nreadbyte = m_commUart.readAll();
        dataToStruct(nreadbyte);
        m_serialPortLock = false;
    }
}

/*
 * 串口发送数据
 * nsndbytes  : 待发送数据
 * nreadsizes : 待接收数据长度
 */
void TLR::serialPortWrite(const QList<QByteArray> &nsndbytes, const QList<int> nreadsizes)
{
    if(nsndbytes.size() == nreadsizes.size()) {
        if(m_commUart.isOpen() && !m_serialPortLock) {
            m_serialPortLock = true;
            int nindex = 0;
            for(const QByteArray &nsndbyte:nsndbytes) {
                int nreadsize = nreadsizes.at(nindex);
                m_commUart.clear();
                m_commUart.write(nsndbyte);
                //等待发送完成以及接收完成
                delayMs(int((nsndbyte.size()*10.5/m_commUart.baudRate()*1000 + nreadsize*10.5/m_commUart.baudRate()*1000 + 20)*2));
                QByteArray nreadbyte = m_commUart.readAll();
                dataToStruct(nreadbyte);
                nindex += 1;
            }
            m_serialPortLock = false;
        }
    }
}

/**
 * @brief 初始化
 */
void TLR::init()
{
    m_myIP = getTMyIPAsnIP(getAllAddressIPv4().value(0));
    //加载设置
    QSettings settingsINI(QApplication::applicationDirPath() + "/config.ini",QSettings::IniFormat);
    settingsINI.beginGroup("config");
    m_language = settingsINI.value("language").toString();
    m_filePath = settingsINI.value("path").toString();
    settingsINI.endGroup();
    //UDP2305收到数据
    connect(m_udpSockAny,&QUdpSocket::readyRead,this,&TLR::slotUdpSockAnyReadyRead);
}

/**
 * @brief 打开保存文件的路径
 * @param filePath 文件路径
 */
void TLR::saveFilePath(const QString &filePath)
{
    m_filePath = filePath;
    QSettings settingsINI(QApplication::applicationDirPath() + "/config.ini",QSettings::IniFormat);
    settingsINI.beginGroup("config");
    settingsINI.setValue("path",filePath);
    settingsINI.endGroup();
}

/**
 * @brief 设备IP从INI文件读取
 * @return
 */
QString TLR::devIPFromINI()
{
    QString devIP = "192.168.0.11";
    QSettings settingsINI(QApplication::applicationDirPath() + "/config.ini",QSettings::IniFormat);
    settingsINI.beginGroup("config");
    devIP = settingsINI.value("devIP").toString();
    if(devIP.isEmpty()) {
        devIP = "192.168.0.11";
    }
    settingsINI.endGroup();
    return devIP;
}

/**
 * @brief 设备IP保存到INI文件
 * @param devIP
 */
void TLR::devIPToINI(const QString &devIP)
{
    QSettings settingsINI(QApplication::applicationDirPath() + "/config.ini",QSettings::IniFormat);
    settingsINI.beginGroup("config");
    settingsINI.setValue("devIP",devIP);
    settingsINI.endGroup();
}

/*
 * 数据分配给结构体
 * nreadbyte : 数据
 */
void TLR::dataToStruct(const QByteArray &nreadbyte)
{
    if(!nreadbyte.isEmpty()){
        const TUDPSysPara *pudpsyspara = reinterpret_cast<const TUDPSysPara*>(nreadbyte.data());
        int para_sta_add = pudpsyspara->ParaStaAdd;
        int para_num = pudpsyspara->ParaNum;
        for(int i=0;i<m_lrStructModel.size();i++) {
            TLRStruct &lrStruct = m_lrStructModel.m_lrstructModel[i];
            if(lrStruct.isMatch(para_sta_add,para_num)) {
                //读取
                if(pudpsyspara->CmdType == 0x03) {
                    lrStruct.memParaCopy(pudpsyspara->Para,para_sta_add - lrStruct.paraStaAdd,pudpsyspara->ParaNum);
                    if(lrStruct.isLast(para_sta_add,pudpsyspara->ParaNum)) {
                        emit sigStructDataUpdate(i);
                        emit sigUpdateCommHint("读取成功");
                    }
                    emit sigStructDataUpdate_Calib(para_sta_add,lrStruct.paraStaAdd,para_num,lrStruct.memData);
                }
                //下发
                else {
                    emit sigUpdateCommHint("下发成功",false);
                }
                break;
            }
        }
    }
}

/*
 * 收到UDP数据
 */
void TLR::slotUdpSockAnyReadyRead()
{
    while (m_udpSockAny->hasPendingDatagrams()) {
        QNetworkDatagram ndatagram = m_udpSockAny->receiveDatagram();
        QByteArray nreadbyte = ndatagram.data();
        dataToStruct(nreadbyte);
    }
}
